#include <cstdio>//uncle-lu
#include <cstring>
#include <queue>
#include <algorithm>

const int N = 100000 + 1;
const int M = 1000000 + 1;

void add_edge(int, int, int);
int Find_Father(int);
void BFS();

int line[N];
struct node_2{
	int x, y, val;
	friend bool operator<(const node_2 a,const node_2 b)
	{
		if(line[a.y]==line[b.y])return a.val<b.val;
		return line[a.y]>line[b.y];
	}
};
node_2 SetEdge[M*2];
struct node{
	int v, next, val;
};
node edge[M*2];
int head[N];
int n, m, cnt, top, count;
int Father[N];
bool visit[N];

void add_edge(int x, int y, int val)
{
	edge[++cnt].v = y;
	edge[cnt].next = head[x];
	edge[cnt].val = val;
	head[x] = cnt;
	return ;
}

int Find_Father(int x) { return Father[x] == x ? x : Father[x] = Find_Father(Father[x]); } 

struct qunode{
	int x,fa;
};
void BFS()
{
	std::queue<qunode>qu;
	qu.push((qunode){1,0});
	visit[1] = true;
	
	while(!qu.empty())
	{
		qunode s = qu.front();
		int now = s.x;
		qu.pop();
		for(int i=head[now];~i;i=edge[i].next)
		{
			if(edge[i].v == s.fa)continue;
			SetEdge[++top]=(node_2){now, edge[i].v, edge[i].val};
			if(!visit[edge[i].v]){
				visit[edge[i].v] = true;
				qu.push((qunode){ edge[i].v, now });
			}
		}
	}
	return ;
}

int main()
{
	memset(head,-1,sizeof(head));

	scanf("%d %d", &n, &m);
	for(int i=1; i<=n; ++i)
		scanf("%d", &line[i]);

	for(int i=1; i<=n; ++i)
		Father[i] = i;

	int x, y, val;
	for(int i=1; i<=m; ++i)
	{
		scanf("%d %d %d", &x, &y, &val);

		if(line[x]<=line[y])add_edge(y,x,val);
		if(line[x]>=line[y])add_edge(x,y,val);
	}

	BFS();

	std::sort(SetEdge+1, SetEdge+1+top);

	long long int ans = 0;
	for(int i=1; i<=top; ++i)
	{
		int xx = Find_Father(SetEdge[i].x), yy = Find_Father(SetEdge[i].y);
		if(xx != yy)
		{
			ans += (long long int)SetEdge[i].val;
			Father[yy] = xx;
		}
	}

	for(int i=1;i<=n;++i)
		if(visit[i])count++;

	printf("%d %lld", count, ans);

	return 0;
}
